package com.augurit.wf.bi.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;
import org.springside.modules.orm.PropertyFilter;

import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.PageUtils;
import com.augurit.common.util.lang.StringUtils;
import com.augurit.wf.bi.convert.WfPageElementConvertor;
import com.augurit.wf.bi.service.IWfPageElementService;
import com.augurit.wf.bi.web.form.WfActElemPrivDefForm;
import com.augurit.wf.bi.web.form.WfPageElementForm;
import com.augurit.wf.common.dao.WfActElemPrivDefDao;
import com.augurit.wf.common.dao.WfBusTemplateDao;
import com.augurit.wf.common.dao.WfPageElementDao;
import com.augurit.wf.common.dao.WfTemplateElementRefDao;
import com.augurit.wf.common.entity.WfActElemPrivDef;
import com.augurit.wf.common.entity.WfBusTemplate;
import com.augurit.wf.common.entity.WfPageElement;
import com.augurit.wf.common.entity.WfTemplateElementRef;
import java.lang.IllegalArgumentException;

@Service
@Transactional
public class WfPageElementServiceImpl implements IWfPageElementService{

	public static String SQL_LOAD_FIELD_ELEMS = " and elem.element_type = 'field'";
	
	public static String SQL_LOAD_BUTTON_ELEMS = " and elem.element_type = 'button'";
	
	public static String SQL_LOAD_CONTAIN_ELEMS = " and ( elem.element_type = 'form' or elem.element_type = 'panel' or elem.element_type = 'toolbar')";
	
	@Autowired
	private WfPageElementDao wfPageElementDao;
	
	@Autowired
	private WfTemplateElementRefDao wfTemplateElementRefDao;
	
	@Autowired
	private WfActElemPrivDefDao wfActElemPrivDefDao;
	
	@Autowired
	private WfBusTemplateDao wfBusTemplateDao;
	
	/**
	 * 删除公共页面元素
	 * @param ids
	 */
	public void deletePublicElements(Long...ids){
		if(ids != null && ids.length > 0){
			for(Long id:ids){
				//删除公共页面元素与所有模板的关联关系
				List<WfTemplateElementRef> templateRefs = wfTemplateElementRefDao.findBy("elementId", id);
				if(templateRefs != null && templateRefs.size() > 0)
					wfTemplateElementRefDao.delete(templateRefs);
				
				//删除该公共页面元素的权限信息
				List<WfActElemPrivDef> privRefs = wfActElemPrivDefDao.findBy("elementId", id);
				if(privRefs != null && privRefs.size() > 0)
					wfActElemPrivDefDao.delete(privRefs);
				
				//删除页面元素本身
				wfPageElementDao.delete(id);
			}
		}
	}
	
	/**
	 * 根据主键获取Form对象
	 */
	@Transactional(readOnly = true)
	public WfPageElementForm get(Long id) {
		if(id == null){
			throw new IllegalArgumentException("WfPageElement id is null!");
		}
		String sql = "select elem.*, parent.element_code as parentElemCode from wf_page_element elem left join wf_page_element parent on elem.parent_id = parent.id where elem.id=?";
		SQLQuery query = wfPageElementDao.getSession().createSQLQuery(sql).addEntity(WfPageElement.class).addScalar("parentElemCode");
		query.setParameter(0, id);
		
		Object[] objs = (Object[])query.uniqueResult();
		if(objs == null){
			throw new RuntimeException("Can't find WfPageElement entity by id: " + id);
		}
		WfPageElementForm form = WfPageElementConvertor.convertVoToForm((WfPageElement)objs[0]);
		form.setParentElementCode((String)objs[1]);
		return form;
	}
	
	/**
	 * 根据页面元素id获取
	 * @param elementCode
	 * @return
	 */
	@Transactional(readOnly = true)
	public WfPageElementForm getByElementCode(String elementCode){
		WfPageElement entity = wfPageElementDao.findUniqueBy("elementCode", elementCode);
		return WfPageElementConvertor.convertVoToForm(entity);
	}
	
	/**
	 * 根据页面元素id列表获取页面元素
	 * @param elementCodes
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<WfPageElementForm> batchGetByElementIds(List<String> elementCodes){
		String[] elements = new String[elementCodes.size()];
		if(elementCodes != null && elementCodes.size() > 0){
			StringBuilder hql = new StringBuilder("select elem from WfPageElement elem where ");
			hql.append(HqlUtils.buildOrCondition("elem", "elementCode", elementCodes.toArray(elements)));
			
			List<WfPageElement> entities = wfPageElementDao.find(hql.toString());
			return WfPageElementConvertor.convertVoListToFormList(entities);
		}
		return null;
	}
	
	
	
	/**
	 * 删除Form对象列表
	 */
	public void delete(Long... ids) {
		wfPageElementDao.delete(ids);
	}

	/**
	 * 保存新增或修改的Form对象列表
	 */
	public void save(WfPageElementForm... forms) {
		if(forms != null)
			for(WfPageElementForm form : forms)
				this.save(form);
	}
	
	/**
	 * 保存新增或修改的Form对象
	 */
	public void save(WfPageElementForm form){
		
		if(form != null){
			WfPageElement entity = null;
			
			//准备VO对象
			if(form != null && form.getId() != null){
				entity = wfPageElementDao.get(form.getId());
			}else{
				entity = new WfPageElement();
			}
			
			//属性值转换
			WfPageElementConvertor.convertFormToVo(form, entity);
			
			//保存
			wfPageElementDao.save(entity);
			
			//回填ID属性值
			form.setId(entity.getId());
		}
	}

	/**
	 * 根据Form对象的查询条件作分页查询
	 */
	@Transactional(readOnly = true)
	public Page<WfPageElementForm> search(Page<WfPageElementForm> page, WfPageElementForm form) {
		// 建立新的分页对象
		Page pg = PageUtils.newPageInstance(page);
		
		// 查询语句及参数
		StringBuilder hql = new StringBuilder("from WfPageElement ps where 1 = 1");
		List values = new ArrayList();
		
		// 查询条件
		if(form != null){
			if(StringUtils.isNotBlank(form.getElementCode())){
				hql.append(" and ps.elementId like ?");
				values.add("%" + form.getElementCode().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementName())){
				hql.append(" and ps.elementName like ?");
				values.add("%" + form.getElementName().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementGroup())){
				hql.append(" and ps.elementGroup like ?");
				values.add("%" + form.getElementGroup().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementType())){
				hql.append(" and ps.elementType = ?");
				values.add(form.getElementType());
			}
			if(StringUtils.isNotBlank(form.getIsPublic())){
				hql.append(" and ps.isPublic = ?");
				values.add(form.getIsPublic());
			}
			if(StringUtils.isNotBlank(form.getIsActive())){
				hql.append(" and ps.isActive = ?");
				values.add(form.getIsActive());
			}
		}
		
		//排序
		hql.append(HqlUtils.buildOrderBy(page, "ps"));
		
		// 执行分页查询操作
		wfPageElementDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfPageElementForm> list = WfPageElementConvertor.convertVoListToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 利用外连接多表关联查询
	 * @param page
	 * @param form
	 * @return
	 */
	@Transactional(readOnly = true)
	public Page<WfPageElementForm> cascadeSearchBySql(Page<WfPageElementForm> page, WfPageElementForm form){
		
		// 建立新的分页对象
		@SuppressWarnings("unchecked")
		Page pg = PageUtils.newPageInstance(page);
		
		StringBuilder sql = new StringBuilder("select elem.*, tmp.template_name from wf_page_element elem");
		List<Object> values = new ArrayList<Object>();
		
		sql.append( " left join wf_template_element_ref ref on elem.id = ref.element_id ");
		sql.append(" left join wf_bus_template tmp on ref.template_id = tmp.id where 1 = 1");
		
		// 查询条件
		if(form != null){
			if(StringUtils.isNotBlank(form.getElementCode())){
				sql.append(" and elem.element_code like ?");
				values.add("%" + form.getElementCode().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementName())){
				sql.append(" and elem.element_name like ?");
				values.add("%" + form.getElementName().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementGroup())){
				sql.append(" and elem.element_group like ?");
				values.add("%" + form.getElementGroup().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementType())){
				sql.append(" and elem.element_type = ?");
				values.add(form.getElementType());
			}
			if(StringUtils.isNotBlank(form.getIsPublic())){
				sql.append(" and elem.is_public = ?");
				values.add(form.getIsPublic());
			}
			if(StringUtils.isNotBlank(form.getIsActive())){
				sql.append(" and elem.is_active = ?");
				values.add(form.getIsActive());
			}
			if(StringUtils.isNotBlank(form.getTemplateName())){
				sql.append(" and tmp.template_name like ?");
				values.add("%" + form.getTemplateName().trim() + "%");
			}
			if(form.getTemplateId() != null){
				sql.append(" and tmp.id = ?");
				values.add(form.getTemplateId());
			}
			
		}	
		
		String countSql = "select count(*) from (" + sql.toString() + ")";
		Query query1 = wfPageElementDao.getSession().createSQLQuery(countSql.toString());
		if(values != null && values.size() > 0){
			int i = 0;
			for(Object param:values){
				query1.setParameter(i++, param);
			}
		}
		BigDecimal count = (BigDecimal)query1.uniqueResult();
		
		sql.append(" order by tmp.template_name ");
		Query query = wfPageElementDao.getSession()
						.createSQLQuery(sql.toString())
						.addEntity(WfPageElement.class)
						.addScalar("template_name");
		if(values != null && values.size() > 0){
			int i = 0;
			for(Object param:values){
				query.setParameter(i++, param);
			}
		}
		query.setFirstResult(page.getFirst());
		query.setMaxResults(page.getPageSize());
		
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfPageElementForm> list = WfPageElementConvertor.convertMulEntityListToFormList(query.list());
		PageUtils.copy(pg, list, page);
		page.setTotalCount(count.intValue());
		return page;
		
	}
	
	/**
	 * 根据过滤条件列表作分页查询
	 */
	@Transactional(readOnly = true)
	public Page<WfPageElementForm> search(Page<WfPageElementForm> page, List<PropertyFilter> filters) {
		// 建立新的分页对象
		Page<WfPageElement> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		wfPageElementDao.findPage(pg, filters);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfPageElementForm> list = WfPageElementConvertor.convertVoListToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 获取子页面元素
	 * @param parentElementId
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<WfPageElementForm> getChildElements(String parentElementId){
		return getChildElements(parentElementId, " order by ps.elementSortNo asc");
	}
	
	/**
	 * 分组获取子页面元素
	 * @param parentElementId
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<WfPageElementForm> getChildElementsByGroup(String parentElementId){
		return getChildElements(parentElementId, " order by ps.groupSortNo asc, ps.elementSortNo asc");
	}
	
	/**
	 * 获取子页面元素
	 * @param parentElementId
	 * @return
	 */
	@Transactional(readOnly = true)
	private List<WfPageElementForm> getChildElements(String parentElementId, String orderBy){
		if(parentElementId != null && parentElementId.trim().length() > 0){
			String hql = "from WfPageElement ps where ps.parentElementId=?";
			
			if(orderBy != null && orderBy.trim().length() > 0)
				hql += orderBy;
			
			List<WfPageElement> list = wfPageElementDao.find(hql, parentElementId);
			return WfPageElementConvertor.convertVoListToFormList(list);
		}else
			return null;
	}
	
	/**
	 * 根据视图名称初始化一个默认权限的WfActElemPrivDef实体
	 * @param form
	 * @param viewName
	 * @return
	 */
	private WfActElemPrivDef initActElemPrivDefByView(WfPageElementForm form, String viewName){
		WfBusTemplate template = wfBusTemplateDao.get(form.getTemplateId());
		
		if(template == null){
			throw new NullPointerException("不能找到templateId:" + form.getTemplateId() + " 对应的模板");
		}
		
		WfActElemPrivDef defaultPriv = new WfActElemPrivDef();
		
		//设置templateId
		defaultPriv.setTemplateId(form.getTemplateId());
		
		if(template.getWfDefVersion() == null){
			throw new NullPointerException("templateId为：" + form.getTemplateId() + " 的模板还有定义相应的流程");
		}
		//设置版本
		defaultPriv.setVersion(template.getWfDefVersion());
		
		//设置视图名称
		defaultPriv.setViewName(viewName);
		//设置elementId
		defaultPriv.setElementId(form.getId());
		
		//字段类型页面元素
		if(form.getElementType().equals(WfPageElementForm.FIELD_ELEM_TYPE)){
			defaultPriv.setIsLock(WfPageElementForm.LOCKED);
		}
		//按钮类型页面元素
		else if(form.getElementType().equals(WfPageElementForm.BUTTON_ELEM_TYPE)){
			defaultPriv.setIsHidden(WfPageElementForm.HIDDEN);
		}
		return defaultPriv;
	}
	
	/**
	 * 为指定模板添加页面元素
	 * @param form
	 */
	public void addPageElement(WfPageElementForm form){
		//如果是为某一模板添加页面元素
		if(form.getTemplateId() != null ){
			
			//新增页面元素, 或者向模板中添加公共页面元素
			if(form.getId() == null || WfPageElementForm.PUBLIC.equals(form.getIsPublic())){
				//如果是新增页面元素，先保存
				if(form.getId() == null)
					this.save(form);
				
				//向权限表中添加该页面元素的默认权限控制信息，即对于已办、办结视图，字段页面元素是锁定的，按钮是隐藏的
				if(form.getElementType().equals(WfPageElementForm.FIELD_ELEM_TYPE) || form.getElementType().equals(WfPageElementForm.BUTTON_ELEM_TYPE)){
					
					WfActElemPrivDef ybDefaultPriv = initActElemPrivDefByView(form, WfActElemPrivDefForm.YB_VIEW);
					WfActElemPrivDef bjDefaultPriv = initActElemPrivDefByView(form, WfActElemPrivDefForm.BJ_VIEW);
					
					wfActElemPrivDefDao.save(ybDefaultPriv);
					wfActElemPrivDefDao.save(bjDefaultPriv);
				}
			}
			
			//添加关联
			WfTemplateElementRef entity = new WfTemplateElementRef();
			entity.setTemplateId(form.getTemplateId());
			entity.setElementId(form.getId());
			wfTemplateElementRefDao.save(entity);
		}
		else{
			this.save(form);
		}
	}
	
	
	/**
	 * 获取公共的页面元素
	 * @param page
	 * @param form
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<WfPageElementForm> getAllPublicElems(){
		String hql = "from WfPageElement elem where elem.isPublic = '1'";
		List<WfPageElement> entities = wfPageElementDao.find(hql);
		return WfPageElementConvertor.convertVoListToFormList(entities);
	}
	
	
	/**
	 * 获取公共的页面元素
	 * @param page
	 * @param form
	 * @return
	 */
	@Transactional(readOnly = true)
	public Page<WfPageElementForm> getPublicElements(Page<WfPageElementForm> page, WfPageElementForm form){
		// 建立新的分页对象
		Page<WfPageElement> pg = PageUtils.newPageInstance(page);
		
		StringBuilder hql = new StringBuilder("from WfPageElement ps where ps.isPublic = '1'");
		List<Object> values = new ArrayList<Object>();
		
		// 查询条件
		if(form != null){
			if(StringUtils.isNotBlank(form.getElementCode())){
				hql.append(" and ps.elementCode like ?");
				values.add("%" + form.getElementCode().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementName())){
				hql.append(" and ps.elementName like ?");
				values.add("%" + form.getElementName().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementGroup())){
				hql.append(" and ps.elementGroup like ?");
				values.add("%" + form.getElementGroup().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementType())){
				hql.append(" and ps.elementType = ?");
				values.add(form.getElementType());
			}
			if(StringUtils.isNotBlank(form.getIsActive())){
				hql.append(" and ps.isActive = ?");
				values.add(form.getIsActive());
			}
		}
		
		//排序
		hql.append(HqlUtils.buildOrderBy(page, "ps"));
		
		// 执行分页查询操作
		wfPageElementDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfPageElementForm> list = WfPageElementConvertor.convertVoListToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
		
	}
	
	/**
	 * 获取公共的容器类页面元素
	 * @param page
	 * @param form
	 * @return
	 */
	public Page<WfPageElementForm> getPublicContainElements(Page<WfPageElementForm> page, WfPageElementForm form){
		// 建立新的分页对象
		Page<WfPageElement> pg = PageUtils.newPageInstance(page);
		
		StringBuilder hql = new StringBuilder("from WfPageElement ps where ps.isPublic = '1'");
		List<Object> values = new ArrayList<Object>();
		
		hql.append(" and (");
		for(int i = 0; i < WfPageElementForm.childElemsInContain.length; i++){
			if(i == 0)
				hql.append(" ps.elementType = ?");
			else
				hql.append(" or ps.elementType = ?");
			values.add(WfPageElementForm.childElemsInContain[i]);
				
		}
		hql.append(")");
		
		// 查询条件
		if(form != null){
			if(StringUtils.isNotBlank(form.getElementCode())){
				hql.append(" and ps.elementId like ?");
				values.add("%" + form.getElementCode().trim() + "%");
			}
			if(StringUtils.isNotBlank(form.getElementName())){
				hql.append(" and ps.elementName like ?");
				values.add("%" + form.getElementName().trim() + "%");
			}
		}
		
		//排序
		hql.append(HqlUtils.buildOrderBy(page, "ps"));
		
		// 执行分页查询操作
		wfPageElementDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<WfPageElementForm> list = WfPageElementConvertor.convertVoListToFormList(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 是否存在elemCode的页面元素
	 * @param elementCode
	 * @param elementId
	 * @return
	 */
	public boolean isElemCodeExist(String elementCode, Long elementId){
		if(elementCode == null){
			throw new IllegalArgumentException("elementCode is not null");
		}
		
		WfPageElementForm formFindByCode = this.getByElementCode(elementCode);
		if(formFindByCode == null)
			return false;
		
		if(elementId != null){
			WfPageElementForm formFindByElementId = this.get(elementId);
			return !formFindByCode.getElementCode().equals(formFindByElementId.getElementCode());
		}
		return true;
	}
}
